package lol.clann.bukkit.pluginboot.config.jackson.tileentity;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleModule;
import lol.clann.bukkit.pluginboot.util.NBTUtils;
import lol.clann.bukkit.pluginboot.util.TileEntityUtils;
import lol.clann.clannboot.annotation.inject.Inject;
import lol.clann.clannboot.annotation.svc.PostInstance;
import lol.clann.clannboot.annotation.svc.Service;
import lol.clann.clannboot.config.jackson.Jackson;
import lol.clann.clannboot.config.jackson.fill.BaseJsonDeserializer;
import lombok.Getter;
import lombok.Setter;

import java.io.IOException;

/**
 * @author pyz
 * @date 2018/10/12 下午10:04
 */
@Service(priority = Integer.MAX_VALUE - 100)
public class TileEntityRegister {

    @Inject
    private TileEntityUtils tileEntityUtils;
    @Inject
    private ObjectMapper objectMapper;

    @PostInstance
    private void init() {
        Jackson.addSerializer(TileEntityUtils.classNMSTileEntity.getHandle(), new JsonSerializer<Object>() {
            @Override
            public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
                Object tag = tileEntityUtils.toCompound(value);
                gen.writeObject(tag);
            }
        });
        Jackson.addDeserializer(TileEntityUtils.classNMSTileEntity.getHandle(), new BaseJsonDeserializer<Object>() {
            @Override
            protected Object create(JsonParser p, DeserializationContext context) throws IOException, JsonProcessingException {
                throw new UnsupportedOperationException();
//                Object tag = objectMapper.readValue(p, NBTUtils.classNBTTagCompound.getHandle());
//                return tileEntityUtils.fromCompound(tag);
            }

            @Override
            protected Object fill(Object value, JsonParser p, DeserializationContext context) throws IOException, JsonProcessingException {
                Object tag = objectMapper.readValue(p, NBTUtils.classNBTTagCompound.getHandle());
                tileEntityUtils.fill(value, tag);
                return value;
            }
        });
    }

    public static void main(String[] ags) throws IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(B.class, new JsonSerializer<B>() {
            @Override
            public void serialize(B value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
                gen.writeObject(new D());
            }
        });
        simpleModule.addDeserializer(B.class, new JsonDeserializer<B>() {
            @Override
            public B deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
                D d = objectMapper.readValue(p, D.class);
                return new B();
            }
        });
        objectMapper.registerModule(simpleModule);
        JsonNode node = objectMapper.valueToTree(new A());
        String text = node.toString();
        A a = objectMapper.readValue(node.traverse(), A.class);
        System.out.println(a);
    }

    @Getter
    @Setter
    private static class A {
        int a = 1;
        B d = new B();
        int b = 2;
        String c = "aaa";
    }

    @Getter
    @Setter
    private static class B {
        int e = 1;
        int f = 2;
        boolean g = false;
        int[] h = new int[]{1, 23};
        byte[] i = new byte[]{1, 23};
        float[] j = new float[]{1, 23};
    }

    @Getter
    @Setter
    private static class C {
        int a = 1;
        int b = 2;
        String c = "aaa";
        B d = new B();
    }

    @Getter
    @Setter
    private static class D {
        int e = 1;
        int f = 2;
        boolean g = false;
        int[] h = new int[]{1, 23};
        byte[] i = new byte[]{1, 23};
        float[] j = new float[]{1, 23};
    }
}
